// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: linchuan

#include "coin2/exchange/ftx_common/api_order/native_rest_async_asio_subscriber.h"

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>

#include <nlohmann/json.hpp>

#include "coin2/base/log.h"

namespace coin2::exchange::ftx_common::api_order {

void FtxRestAsyncAsioSubscriber::QueryBalance() {
  auto http_context = rest_client()->QueryBalance();
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&FtxRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void FtxRestAsyncAsioSubscriber::QueryPosition() {
  auto http_context = rest_client()->QueryPosition();
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&FtxRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void FtxRestAsyncAsioSubscriber::QueryOpenOrders(const std::string& native_symbol) {
  RestParams params;
  if (!native_symbol.empty()) {
    params.set_market(native_symbol);
  }
  auto http_context = rest_client()->QueryOpenOrders(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&FtxRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void FtxRestAsyncAsioSubscriber::QueryAllOrders(const std::string& native_symbol) {
  RestParams params;
  if (!native_symbol.empty()) {
    params.set_market(native_symbol);
  }
  auto http_context = rest_client()->QueryOrders(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&FtxRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void FtxRestAsyncAsioSubscriber::QueryFills(const std::string& native_symbol) {
  RestParams params;
  if (!native_symbol.empty()) {
    params.set_market(native_symbol);
  }
  auto http_context = rest_client()->QueryTrades(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&FtxRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void FtxRestAsyncAsioSubscriber::QueryTransfer() {
  RestParams params;
  auto http_context = rest_client()->QueryDeposits(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&FtxRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);

  http_context = rest_client()->QueryWithdraws(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&FtxRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void FtxRestAsyncAsioSubscriber::SubscribeAsync() {
  AddPeriodicTask(
      std::bind(&FtxRestAsyncAsioSubscriber::QueryBalance, this),
      config_.query_account_balance_period_sec(),
      "query_balance");

  AddPeriodicTask(
      std::bind(&FtxRestAsyncAsioSubscriber::QueryPosition, this),
      config_.query_account_position_period_sec(),
      "query_position");

  if (is_readonly_order_system_ && symcache_->is_spot()) {
    AddPeriodicTask(
        std::bind(&FtxRestAsyncAsioSubscriber::QueryTransfer, this),
        config_.query_account_balance_period_sec(),
        "query_transfer");
  }

  const auto symbol_list = native_symbols();

  AddPeriodicTask(
      std::bind(&FtxRestAsyncAsioSubscriber::QueryOpenOrders, this, std::placeholders::_1),
      config_.query_open_orders_period_sec(),
      "query_open_orders",
      symbol_list);

  AddPeriodicTask(
      std::bind(&FtxRestAsyncAsioSubscriber::QueryAllOrders, this, std::placeholders::_1),
      config_.query_cancel_orders_period_sec(),
      "query_all_orders",
      symbol_list);

  AddPeriodicTask(
      std::bind(&FtxRestAsyncAsioSubscriber::QueryFills, this, std::placeholders::_1),
      config_.query_fill_period_sec(),
      "query_fills",
      symbol_list);
}

}  // namespace coin2::exchange::ftx_common::api_order
